package com.demo.cryptology.symmetric;


import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

/**
 *  高级加密标准（Advanced Encryption Standard，AES），
 *  又称Rijndael加密法，是美国联邦政府采用的一种区块加密标准。
 *  这个标准用来替代原先的DES，已经被多方分析且广为全世界所使用。
 *  经过五年的甄选流程，高级加密标准由美国国家标准与技术研究院（NIST）于2001年11月26日发布于FIPS PUB 197，并在2002年5月26日成为有效的标准。2006年，高级加密标准已然成为对称密钥加密中最流行的算法之一。
 *        AES的区块长度固定为128 位元，密钥长度则可以是128，192或256位元。
 */
public class AES {

    public static byte[] encrypt(byte[] src, String password) throws Exception {

        SecretKeySpec keySpec = getSecretKeySpec(password);
        //创建一个密钥工厂，然后用它把DESKeySpec转换成
        //cipher对象世纪完成加密操作
        Cipher cipher = Cipher.getInstance("AES");
        //用密钥初始化cipher对象
        cipher.init(cipher.ENCRYPT_MODE, keySpec);
        //现在，获取数据并加密
        //正式执行加密操作
        byte[] r = cipher.doFinal(src);
        return encoder.encode(r);
    }


    public static byte[] decrypt(byte[] src, String password) throws Exception {
        src = decoder.decode(src);
        SecretKeySpec keySpec = getSecretKeySpec(password);
        //创建一个密钥工厂，然后用它把DESKeySpec转换成
        //cipher对象世纪完成加密操作
        Cipher cipher = Cipher.getInstance("AES");
        //用密钥初始化cipher对象
        cipher.init(cipher.DECRYPT_MODE, keySpec);
        //现在，获取数据并加密
        //正式执行加密操作
        byte[] r = cipher.doFinal(src);
        return r;
    }

    private static SecretKeySpec getSecretKeySpec(String password) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(password.getBytes());
        kgen.init(128, random);
        SecretKey secretKey = kgen.generateKey();
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
        return keySpec;
    }


    static final Base64.Decoder decoder = Base64.getDecoder();
    static final Base64.Encoder encoder = Base64.getEncoder();

    public static void main(String[] args) throws Exception {
        String str = "代价密数据,@00asdfuiouoeqw。。";
        System.out.println("加密前:" + str);
        //长度是8的倍数
        String password = "1234567890123456";
        byte[] result = AES.encrypt(str.getBytes(), password);
        System.out.println("加密后:" + new String(result));

        byte[] decryResult = AES.decrypt(result, password);
        System.out.println("解密后:" + new String(decryResult));

    }
}
